const fs = require('fs')
const moment = require('moment')
const {
  OrderDirection,
  // LogType,
  // StoreName: { OPEN_ORDER_INFO },
  // OrderType
  XFactorIndex
} = require('./constants')
const Decimal = require('decimal.js')

let logType = 'sub'

let _formatLogParams = null
class Service {
  addLog (str, str2) {
    fs.appendFileSync(
      `./log/${logType}/${moment().format('YYYYMMDDHH')}.txt`,
      `${str}${str2 ? ` ${str2}` : ''}\n`,
      'utf8',
      err => {
        if (err) {
          throw err
        }
        console.log(str.replace('\n', ' '), str2)
      }
    )
  }
  initFormatLog (params) {
    _formatLogParams = params
  }
  addLogParams (params) {
    _formatLogParams = {
      ...(_formatLogParams || {}),
      ...params
    }
  }
  clearFormatLog () {
    _formatLogParams = null
  }
  formatLog ({ title, type }, doNotAddLog) {
    if (!title || !_formatLogParams) return
    const {
      bollUp,
      price,
      bollDown,
      bollWidth,
      rsi,
      minBollWidth,
      stochRSI,
      bollStatus,
      lastBollItem,
      xFactorBuy,
      xFactorSell,
      bollWidthDiff,
      bollUpDiff,
      bollDownDiff
    } = _formatLogParams
    let addLog = this.addLog
    logType = type
    if (doNotAddLog) {
      addLog = console.log
    }
    addLog(`————${title}————`)
    addLog('布林上轨', `${bollUp} (${lastBollItem.upper})`)
    addLog('当前价格', price)
    addLog('布林下轨', `${bollDown} (${lastBollItem.lower})`)
    addLog(
      '布林半径',
      `${bollWidth} (${Decimal(lastBollItem.upper)
        .sub(lastBollItem.lower)
        .div(2)
        .toNumber()
        .toFixed()}) ${bollWidth > minBollWidth ? '>' : '<'} ${minBollWidth}`
    )
    if (bollStatus) addLog('布林带状态', bollStatus)
    if (xFactorBuy) addLog('xFactor(多单)', xFactorBuy || '0')
    if (xFactorSell) addLog('xFactor(空单)', xFactorSell || '0')
    addLog('布林半径变化', bollWidthDiff || '0')
    addLog('布林上轨变化', bollUpDiff || '0')
    addLog('布林下轨变化', bollDownDiff || '0')
    addLog('RSI', rsi)
    addLog('stochRSI', stochRSI)
    addLog('时间', moment().format())
    addLog(doNotAddLog ? ' ' : '\n')
  }

  formatOrderLog (
    { title, orderOpenPrice, stopLossPrice, takeProfitPrice, type },
    doNotAddLog
  ) {
    if (!title || !_formatLogParams) return
    const {
      bollUp,
      price,
      bollDown,
      bollWidth,
      rsi,
      stochRSI,
      minBollWidth,
      lastBollItem,
      xFactorBuy,
      xFactorSell,
      bollStatus,
      bollWidthDiff,
      bollUpDiff,
      bollDownDiff
    } = _formatLogParams
    let addLog = this.addLog
    logType = type
    if (doNotAddLog) {
      addLog = console.log
    }
    addLog(`————${title}————`)
    addLog('开单价格', orderOpenPrice)
    addLog('止损价格', stopLossPrice)
    addLog('止盈价格', takeProfitPrice)
    addLog('布林上轨', `${bollUp} (${lastBollItem.bollUp})`)
    addLog('当前价格', price)
    addLog('布林下轨', `${bollDown} (${lastBollItem.bollDown})`)
    addLog(
      '布林半径',
      `${bollWidth} ${bollWidth > minBollWidth ? '>' : '<'} ${minBollWidth}`
    )
    if (bollStatus) addLog('布林带状态', bollStatus)
    if (xFactorBuy) addLog('xFactor(多单)', xFactorBuy || '0')
    if (xFactorSell) addLog('xFactor(空单)', xFactorSell || '0')
    addLog('布林半径变化', bollWidthDiff || '0')
    addLog('布林上轨变化', bollUpDiff || '0')
    addLog('布林下轨变化', bollDownDiff || '0')
    addLog('RSI', rsi)
    addLog('stochRSI', stochRSI || '0')
    addLog('时间', moment().format())
    addLog(doNotAddLog ? ' ' : '\n')
  }
  setJson (key, data) {
    try {
      fs.writeFileSync(`./store/${key}.json`, JSON.stringify(data, null, 4))
    } catch (error) {
      return null
    }
  }
  getJson (key) {
    try {
      const data = fs.readFileSync(`./store/${key}.json`)
      return data ? JSON.parse(data) : null
    } catch (error) {
      return null
    }
  }

  getOpenOrderInfo ({
    lastBollItem,
    bollUp,
    price,
    bollDown,
    bollWidth,
    orderDirection: _orderDirection
  }) {
    let orderDirection = _orderDirection
    let openOrderInfo
    let orderOpenPrice
    let stopLossPrice
    let takeProfitPrice
    // 通过布林带倾斜度定义xFactor
    let xFactor = 0
    const lastBollWidth = Decimal(lastBollItem.upper)
      .sub(lastBollItem.lower)
      .div(2)
      .toNumber()
      .toFixed()
    let bollWidthDiff = Decimal(bollWidth)
      .sub(lastBollWidth)
      .toNumber()
      .toFixed()
    let bollUpDiff = Decimal(bollUp)
      .sub(lastBollItem.upper)
      .toNumber()
      .toFixed()
    let bollDownDiff = Decimal(lastBollItem.lower)
      .sub(bollDown)
      .toNumber()
      .toFixed()

    // 开单价格基础偏移，是布林轨道变化+布林宽度变化
    const basicSellFactor = Decimal(bollWidthDiff)
      .add(bollUpDiff)
      .toNumber()
    const basicBuyFactor = Decimal(bollWidthDiff)
      .add(bollDownDiff)
      .toNumber()
    let xFactorRatio = 1
    switch (orderDirection) {
      case OrderDirection.SELL:
        if (bollWidthDiff > 35 || bollUpDiff > 45) {
          const bollWidthRatio = bollWidthDiff / 35
          const bollUpRatio = bollUpDiff / 45
          xFactorRatio = Decimal(bollWidthRatio)
            .mul(bollUpRatio)
            .mul(XFactorIndex)
            .toNumber()
          xFactor = Decimal(basicSellFactor)
            .mul(xFactorRatio)
            .toNumber()
            .toFixed()
        } else {
          xFactor = basicSellFactor
        }
        orderOpenPrice = Decimal(price)
          .add(xFactor)
          .toNumber()
          .toFixed()
        // 止损价格是开单价格，反向偏移布林宽度50%
        stopLossPrice = Decimal(orderOpenPrice)
          .add(bollWidth * 0.5)
          .toNumber()
          .toFixed()
        // 取：止盈价格是开单价格，正向偏移移布林宽度80% 和 价格1% 的最大值
        takeProfitPrice = Math.max(
          Decimal(bollUp)
            .sub(bollWidth * 0.8)
            .add(xFactor)
            .toNumber()
            .toFixed(),
          Decimal(orderOpenPrice)
            .sub(price * 0.01)
            .toNumber()
            .toFixed()
        )
        break
      case OrderDirection.BUY:
        if (bollWidthDiff > 35 || bollDownDiff > 45) {
          const bollWidthRatio = bollWidthDiff / 35
          const bollDownRatio = bollDownDiff / 45
          xFactorRatio = Decimal(bollWidthRatio)
            .mul(bollDownRatio)
            .toNumber()
          xFactor = Decimal(basicBuyFactor)
            .mul(xFactorRatio)
            .mul(XFactorIndex)
            .toNumber()
        } else {
          xFactor = basicBuyFactor
        }
        orderOpenPrice = Decimal(price)
          .sub(xFactor)
          .toNumber()
          .toFixed()
        // 止损价格是开单价格，偏移布林宽度50%
        stopLossPrice = Decimal(orderOpenPrice)
          .sub(bollWidth * 0.5)
          .toNumber()
          .toFixed()
        // 取：止盈价格是开单价格，正向偏移移布林宽度80% 和 价格1% 的最小值
        takeProfitPrice = Math.min(
          Decimal(bollDown)
            .add(bollWidth * 0.8)
            .sub(xFactor)
            .toNumber()
            .toFixed(),
          Decimal(orderOpenPrice)
            .add(price * 0.01)
            .toNumber()
        )
        break
      default:
        break
    }

    openOrderInfo = {
      orderOpenPrice,
      stopLossPrice,
      takeProfitPrice,
      xFactor,
      bollWidthDiff,
      bollUpDiff,
      bollDownDiff,
      orderDirection
    }

    return openOrderInfo
  }
  getOneSideOrderInfo () {
    
  }
}
module.exports = new Service()
